#pragma once
#include <memory>
#include <vector>
#include <queue>
#include <ctime>
#include "log.hpp"
#include "thread.hpp"
const static int gthreadnum = 5;

template <typename T>
class threadpool
{
private:
    void QueueLock()
    {
        pthread_mutex_lock(&_mutex);
    }
    void QueueUnlock()
    {
        pthread_mutex_unlock(&_mutex);
    }
    void WakeThread()
    {
        pthread_cond_signal(&_cond);
    }
    void WakeAllThread()
    {
        pthread_cond_broadcast(&_cond);
    }
    void Threadsleep()
    {
        pthread_cond_wait(&_cond, &_mutex);
    }

public:
    threadpool(int threadnum = gthreadnum)
        : _threadnum(threadnum), _waitnum(0), _Isrunning(false), _Startnum(0)
    {
        pthread_mutex_init(&_mutex, nullptr);
        pthread_cond_init(&_cond, nullptr);
    }
    ~threadpool()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_cond);
    }
    void HandlerTask(std::string name)
    {
        while (true)
        {
            QueueLock();
            while (_taskqueue.empty() && _Isrunning) // 空的但是还在跑
            {
                _waitnum++;
                Threadsleep(); // 去阻塞等待
                _waitnum--;
            }
            if (_taskqueue.empty() && !_Isrunning) // 空的而且没跑了
            {
                QueueUnlock();
                std::cout << name << ":quit" << std::endl;
                break;
            }
            // 2.2 如果线程池不退出 && 任务队列不是空的
            // 2.3 如果线程池已经退出 && 任务队列不是空的 --- 处理完所有的任务，然后在退出
            // 3. 一定有任务, 处理任务
            T t = _taskqueue.front();
            _taskqueue.pop();
            if (t())
            {
                std::cout << "mission success" << std::endl;
            } // 执行
            else
            {
                std::cout << "mission fail" << std::endl;
            }
            QueueUnlock();
        }
    }
    bool Enqueue(const T &x)
    {
        bool ret = false;
        QueueLock();
        if (_Isrunning)
        {
            ++_Startnum;
            LOG(INFO, "%s", "ENqueue mission");
            _taskqueue.push(x);
            if (_waitnum > 0)
            {
                WakeThread();
            }
            ret = true;
        }

        QueueUnlock();
        return ret;
    }
    void InitThreadPool()
    {
        for (int num = 0; num < _threadnum; num++)
        {
            std::string name = "Thread:" + std::to_string(num + 1);
            _threadpool.emplace_back(std::bind(&threadpool::HandlerTask, this, std::placeholders::_1), name); // bind绑定类成员函数时,第二个参数必须是this
        }
        LOG(INFO, "%s", "InitPool");
        _Isrunning = true;
    }
    bool ReadyToStart()
    {
        LOG(INFO, "%s", "ReadToStart");
        return _Startnum == _threadnum;
    }
    void Stop()
    {
        QueueLock();
        _Isrunning = false;
        WakeAllThread(); // 不跑了 把剩的任务跑了 唤醒在_cond下等待的所有线程 并执行
        LOG(WARNING, "%s", "STOP");
        QueueUnlock();
    }
    void Wait()
    {
        for (auto &thread : _threadpool)
        {
            //LOG(FATAL, "单例:%s:-%s", thread.name().c_str(), "waiting");
            LOGINTRASH(FATAL, "%s:-%s", thread.name().c_str(), "In trash");
            thread.Join();
        }
    }
    void Start()
    {
        for (auto &thread : _threadpool)
        {
            LOG(INFO, "%s-%lu:%s", thread.name().c_str(),thread.Gettid(), "start");
            thread.Start();
        }
    }
    void Detach(std::string threadname)
    {
        for (auto &thread : _threadpool)
        {
            if (thread.name() == threadname)
            {
                thread.Detach();
            }
        }
    }
    void DetachAll()
    {
        for (auto &thread : _threadpool)
        {
            thread.Detach();
        }
    }
    threadpool<T> &operator=(const threadpool<T> &) = delete;
    threadpool(const threadpool<T> &) = delete;
    // 单例模式 懒汉
    static threadpool<T> *Getinstance()
    {
        if (_instance == nullptr)
        {
            LookGuard guard(&_lock);
            if (_instance == nullptr)
            {
                _instance = new threadpool<T>();
                _instance->InitThreadPool();
                _instance->Start();
                LOG(DEBUG, "%s", "初次创建线程池单例");
                pthread_mutex_unlock(&_lock);
                return _instance;
            }
        }
        LOG(DEBUG, "%s", "获取线程池单例");
        return _instance;
    }

private:
    int _threadnum;
    std::vector<Thread> _threadpool;
    std::queue<T> _taskqueue;

    pthread_mutex_t _mutex;
    pthread_cond_t _cond;
    int _waitnum;
    bool _Isrunning;
    int _Startnum;

    static threadpool<T> *_instance;
    static pthread_mutex_t _lock;
};
template <typename T>
threadpool<T> *threadpool<T>::_instance = nullptr;
template <typename T>
pthread_mutex_t threadpool<T>::_lock = PTHREAD_MUTEX_INITIALIZER;